#pragma once

#include <string>
#include <utility>
#include "Status.h"

namespace streamdb {

struct Object {
    virtual ~Object(){}
    virtual bool isNull() const = 0;
    virtual std::string toString() const = 0; 
};

class Serializable {
public:
    virtual ~Serializable(){}
    virtual Status toBinary(std::string & bin) const = 0;
    virtual Status fromBinary(const std::string & bin) = 0;
};


struct OrderedMessage : public Object, public Serializable{
    int64_t id;
    std::string body;

    ~OrderedMessage() override {}
    OrderedMessage(int64_t id=0, const std::string & body="") : id(id), body(body) {}

    OrderedMessage(const OrderedMessage & msg){
        id = msg.id;
        body = msg.body;
    }
    OrderedMessage(OrderedMessage && msg) {
        //std::cout << "OrderedMessage(&&)" << std::endl;
        //*this = std::move(msg);
        id = std::move(msg.id);
        body = std::move(msg.body);
    }
    OrderedMessage & operator=(OrderedMessage && msg) {
        //std::cout << "OrderedMessage.operator=(&&)" << std::endl;
        id = std::move(msg.id);
        body = std::move(msg.body);
        return *this;
    }
    const OrderedMessage & operator = (const OrderedMessage & msg){
        id = msg.id;
        body = msg.body;
        return *this;
    }

    std::string toString() const override;

    uint64_t size() const{
        return sizeof(id) + body.size();
    }

    bool isNull() const override{
        return this == &(Null);
    }


    bool operator==(const OrderedMessage & object){
        return object.id == id && object.body == body;
    }


    Status toBinary(std::string & bin) const override;
    Status fromBinary(const std::string & bin) override;


    static OrderedMessage Null;
};

}//namespace streamdb

